/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef STREAM_OPERATOR_STREAM_OPERATOR_IMPL_H
#define STREAM_OPERATOR_STREAM_OPERATOR_IMPL_H

#include "stream_operator.h"
#include "stream_thread.h"
#include "host_stream_data_structure.h"
#include "offline_stream_context.h"
#include "offline_stream_operator.h"

namespace OHOS::Camera {
class StreamBase;
class CameraDevice;
class IStreamPipelineCore;
class StreamSupportedConfig;
class CameraCapture;
class StreamOperatorImpl
    : public StreamOperator,
      public StreamThread {
public:
    virtual CamRetCode IsStreamsSupported(OperationMode mode,
        const std::shared_ptr<CameraStandard::CameraMetadata> &modeSetting,
        const std::shared_ptr<StreamInfo> &pInfo,
        StreamSupportType &pType) override;
    virtual CamRetCode CreateStreams(const std::vector<std::shared_ptr<StreamInfo>> &streamInfos) override;
    virtual CamRetCode ReleaseStreams(const std::vector<int> &streamIds) override;
    virtual CamRetCode CommitStreams(OperationMode mode, const std::shared_ptr<CameraStandard::CameraMetadata> &modeSetting) override;
    virtual CamRetCode GetStreamAttributes(std::vector<std::shared_ptr<StreamAttribute>> &attributes) override;
    virtual CamRetCode AttachBufferQueue(int streamId, const OHOS::sptr<OHOS::IBufferProducer> &producer) override;
    virtual CamRetCode DetachBufferQueue(int streamId) override;
    virtual CamRetCode Capture(int captureId, const std::shared_ptr<CaptureInfo> &pInfo,  bool isStreaming) override;
    virtual CamRetCode CancelCapture(int captureId) override;
    virtual CamRetCode ChangeToOfflineStream(const std::vector<int> &streamIds,
        OHOS::sptr<IStreamOperatorCallback> &callback,
        OHOS::sptr<IOfflineStreamOperator> &offlineOperator) override;
    void SetRequestCallback(std::function<void()> cb);

public:
    StreamOperatorImpl(const OHOS::sptr<IStreamOperatorCallback> &callback,
        const std::weak_ptr<CameraDevice> &device);
    virtual ~StreamOperatorImpl();
    StreamOperatorImpl(const StreamOperatorImpl &other) = delete;
    StreamOperatorImpl(StreamOperatorImpl &&other) = delete;
    StreamOperatorImpl& operator=(const StreamOperatorImpl &other) = delete;
    StreamOperatorImpl& operator=(StreamOperatorImpl &&other) = delete;

protected:
    void Run();
    virtual void Process() override;

private:
    RetCode StartThread();
    void ChangeHostStreamInfo(const std::shared_ptr<StreamInfo> &streamInfo, HostStreamInfo &hStreamInfo);
    void StreamBufferCallback(std::shared_ptr<IBuffer> buffer);
    bool ValidStreamInfo(const std::shared_ptr<StreamInfo> &streamInfo);
    bool ValidCaptureInfo(int captureId, const std::shared_ptr<CaptureInfo> &captureInfo);
    void SelectSupportedForMode(OperationMode mode,
        std::vector<std::shared_ptr<StreamSupported>> &streamSupporteds);
    bool IsSupportedForMeta(const std::shared_ptr<CameraStandard::CameraMetadata> &modeSetting);
    void GetTagsForMetadata(const std::shared_ptr<CameraStandard::CameraMetadata> &cameraMetadata, std::vector<MetaType> &tags);
    void GetConfigAbility(std::shared_ptr<CameraStandard::CameraMetadata> &ability);
    void SelectSupportedForStreamInfo(const std::shared_ptr<StreamInfo> &pInfo,
        std::vector<std::shared_ptr<StreamSupported>> &streamSupporteds);
    uint64_t GetCurrentLocalTimeStamp();
    RetCode CreateStream(const std::shared_ptr<StreamInfo> &streamInfo);
    RetCode CreatePipeStream(const std::shared_ptr<StreamInfo> &streamInfo);
    RetCode DestroyStreamPipeline(const std::vector<int> &streamIds);
    RetCode DestroyHostStreamMgr(const std::vector<int> &streamIds);
    void GetStreamTypes(const std::vector<int> &streamIds, std::vector<int32_t> &types);
    RetCode DestroyStreams(const std::vector<int> &streamIds);
    RetCode CreateCapture(int captureId, const std::shared_ptr<CaptureInfo> &captureInfo,
        bool isStreaming, std::shared_ptr<CameraCapture> &cameraCapture);
    void ResultBuffer(int streamId, const std::shared_ptr<IBuffer> &buffer);
    void ConstructCaptureCallback(std::shared_ptr<CaptureCallback> &callback);
    void OnCaptureStarted(int32_t captureId, const std::vector<int32_t> &streamId);
    void OnCaptureEnded(int32_t captureId, const std::vector<std::shared_ptr<CaptureEndedInfo>> &info);
    void OnCaptureError(int32_t captureId, const std::vector<std::shared_ptr<CaptureErrorInfo>> &info);
    void OnFrameShutter(int32_t captureId, const std::vector<int> &streamIds);

private:
    OHOS::sptr<IStreamOperatorCallback> streamOperatorCallback_ = nullptr;
    std::weak_ptr<CameraDevice> cameraDevice_;
    std::shared_ptr<IStreamPipelineCore> streamPipeCore_ = nullptr;
    std::mutex streamMutex_;
    std::map<int, std::shared_ptr<StreamBase>> streamMap_;
    std::unique_ptr<StreamSupportedConfig> config_;
    std::mutex captureMutex_;
    std::map<int, std::shared_ptr<CameraCapture>> camerCaptureMap_;
    std::shared_ptr<CaptureCallback> captureCallbcak_ = nullptr;
    std::function<void()> requestCallback_;
    OHOS::sptr<OfflineStreamOperator> oflstor_ = nullptr;
};
} // end namespace OHOS::Camera
#endif // STREAM_OPERATOR_STREAM_OPERATOR_IMPL_H
